using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
using System.Xml.Linq;
using DotNetNuke.Entities.Modules;

using DesertedRoadStudios.BlogNetNuke.Common;
using DesertedRoadStudios.BlogNetNuke.Components;

namespace DesertedRoadStudios.BlogNetNuke
{
    public partial class Compose : PortalModuleBase
    {
        private bool _isInEditMode = false;

        Label lblAddNewPost;

        // Title
        TextBox tbTitle;
        HtmlControl permalinkLabel;        
        Label lblURL;
        HtmlControl tinyURLLabel;
        Label lblTinyURL;
        HiddenField hfSlug;

        // Post Content/Settings
        DotNetNuke.UI.UserControls.TextEditor tbPost;
        TextBox tbExcerpt;
        CheckBoxList cblDiscussion;
        TextBox tbKeywords;
        TextBox tbDescription;

        // Status
        Label lblStatus;
        RadioButtonList rblStatus;
        LinkButton lbStatusToggle;
        Panel pnlStatus;
        Button btnStatus;
        LinkButton lbStatusCancel;
        HiddenField hfStatus;

        // Date
        Label lblDate;
        LinkButton lbDateToggle;
        Panel pnlDate;
        DropDownList ddlMonth;
        TextBox tbDay;
        TextBox tbYear;
        TextBox tbHour;
        TextBox tbMinute;
        HiddenField hfDate;

        // Categories
        CheckBoxList cblCategories;
        LinkButton lbCategoryAdd;
        Panel pnlCategory;
        TextBox tbCategory;
        DropDownList ddlCategory;
        HiddenField hfCategory;

        // Tags
        TextBox tbTags;
        Panel pnlTags;
        HiddenField hfTags;

        // Buttons
        Button btnSave;
 
        protected void Page_Init(object sender, EventArgs e)
        {
            lblAddNewPost = FindControl("lblAddNewPost") as Label;

            // Title
            tbTitle = FindControl("tbTitle") as TextBox;
            permalinkLabel = FindControl("permalinkLabel") as HtmlControl;
            lblURL = FindControl("lblURL") as Label;
            tinyURLLabel = FindControl("tinyURLLabel") as HtmlControl;
            lblTinyURL = FindControl("lblTinyURL") as Label;
            hfSlug = FindControl("hfSlug") as HiddenField;

            // Post Content/Settings
            tbPost = FindControl("tbPost") as DotNetNuke.UI.UserControls.TextEditor;
            tbExcerpt = FindControl("tbExcerpt") as TextBox;
            cblDiscussion = FindControl("cblDiscussion") as CheckBoxList;
            tbKeywords = FindControl("tbKeywords") as TextBox;
            tbDescription = FindControl("tbDescription") as TextBox;

            // Status
            lblStatus = FindControl("lblStatus") as Label;
            rblStatus = FindControl("rblStatus") as RadioButtonList;
            lbStatusToggle = FindControl("lbStatusToggle") as LinkButton;
            pnlStatus = FindControl("pnlStatus") as Panel;
            hfStatus = FindControl("hfStatus") as HiddenField;

            // Date
            lblDate = FindControl("lblDate") as Label;
            lbDateToggle = FindControl("lbDateToggle") as LinkButton;
            pnlDate = FindControl("pnlDate") as Panel;
            ddlMonth = FindControl("ddlMonth") as DropDownList;
            tbDay = FindControl("tbDay") as TextBox;
            tbYear = FindControl("tbYear") as TextBox;
            tbHour = FindControl("tbHour") as TextBox;
            tbMinute = FindControl("tbMinute") as TextBox;
            hfDate = FindControl("hfDate") as HiddenField;

            // Categories
            cblCategories = FindControl("cblCategories") as CheckBoxList;
            lbCategoryAdd = FindControl("lbCategoryAdd") as LinkButton;
            pnlCategory = FindControl("pnlCategory") as Panel;
            tbCategory = FindControl("tbCategory") as TextBox;
            ddlCategory = FindControl("ddlCategory") as DropDownList;
            hfCategory = FindControl("hfCategory") as HiddenField;

            // Tags
            tbTags = FindControl("tbTags") as TextBox;
            pnlTags = FindControl("pnlTags") as Panel;
            hfTags = FindControl("hfTags") as HiddenField;
            BindTags();
            
            // Buttons
            btnSave = FindControl("btnSave") as Button;
        }

        protected void Page_PreRender(object sender, EventArgs e)
        {
            Page.Header.Controls.Add(new LiteralControl("<link rel=\"StyleSheet\" type=\"text/css\" href=\"/DesktopModules/BlogNetNuke/styles.css\" />"));
        }

        protected void Page_Load(object sender, EventArgs e)
        {
            /*
            DotNetNuke.Security.Permissions.Controls.TabPermissionsGrid grid = new DotNetNuke.Security.Permissions.Controls.TabPermissionsGrid();
            DotNetNuke.Security.Permissions.TabPermissionCollection permCol = grid.Permissions;
            DotNetNuke.Security.Permissions.TabPermissionInfo info = permCol[0];
            */

            BlogNetNukeController bnn = new BlogNetNukeController();

            // Delete Post
            if (!String.IsNullOrEmpty(Request.QueryString["deletePostID"]))
            {
                bnn.SetPostStatus(PortalId, ModuleId, new Guid(Request.QueryString["deletePostID"]), PostStatus.Deleted);
                Response.Redirect(((XDocument)Session["BlogNetNuke"]).Element("params").Element("Blog").Element("BlogDetails").Element("AbsoluteURL").Value);
            }
            
            // If Edit Post
            if (!String.IsNullOrEmpty(Request.QueryString["postID"]))
                _isInEditMode = true;

            if (!IsPostBack)
            {
                // Set Status
                rblStatus.SelectedValue = "2";
                lblStatus.Text = rblStatus.SelectedItem.Text;
                hfStatus.Value = rblStatus.SelectedValue;

                // Set Date
                ddlMonth.SelectedValue = DateTime.Now.ToString("MM");
                tbDay.Text = DateTime.Now.ToString("dd");
                tbYear.Text = DateTime.Now.Year.ToString();
                tbHour.Text = DateTime.Now.ToString("HH");
                tbMinute.Text = DateTime.Now.ToString("mm");
                lblDate.Text = ddlMonth.SelectedItem.Text + " " + tbDay.Text + ", " + tbYear.Text + " @ " + tbHour.Text + ":" + tbMinute.Text;
                hfDate.Value = ddlMonth.SelectedValue + "|" + tbDay.Text + "|" + tbYear.Text + "|" + tbHour.Text + "|" + tbMinute.Text;

                // Load Categories
                hfCategory.Value = "-1"; // Set 'Uncategorized' by default
                BindCategories();

                // Clear Tags from Session
                if (Session["tags"] != null)
                {
                    Session.Remove("tags");
                    pnlTags.Controls.Clear();
                }

                // If Edit Post
                if (!String.IsNullOrEmpty(Request.QueryString["postID"]))
                {
                    try
                    {
                        Guid postID = new Guid(Request.QueryString["postID"]);
                        PostInfo post = bnn.GetPostByPostID(PortalId, ModuleId, postID);

                        lblAddNewPost.Text = "Edit Post";
                        tbTitle.Text = post.PostTitle;
                        TinyURLInfo tinyURL = bnn.GetTinyUrl(postID);
                        if ((tinyURL != null) && (!string.IsNullOrEmpty(tinyURL.DomainName)) && (!string.IsNullOrEmpty(tinyURL.Code)))
                        {
                            tinyURLLabel.Visible = true;
                            lblTinyURL.Text = "http://" + tinyURL.DomainName + "/" + tinyURL.Code;
                        }
                        hfSlug.Value = post.Slug;
                        tbPost.RichText.Text = post.Content;
                        tbExcerpt.Text = post.Excerpt;
                        cblDiscussion.Items[0].Selected = post.AllowComments;
                        tbKeywords.Text = post.Keywords;
                        tbDescription.Text = post.Description;

                        hfStatus.Value = ((int)post.Status).ToString();
                        rblStatus.SelectedValue = hfStatus.Value;
                        lblStatus.Text = rblStatus.SelectedItem.Text;

                        ddlMonth.SelectedValue = post.PublishedDate.ToString("MM");
                        tbDay.Text = post.PublishedDate.ToString("dd");
                        tbYear.Text = post.PublishedDate.Year.ToString();
                        tbHour.Text = post.PublishedDate.ToString("HH");
                        tbMinute.Text = post.PublishedDate.ToString("mm");
                        lblDate.Text = ddlMonth.SelectedItem.Text + " " + tbDay.Text + ", " + tbYear.Text + " @ " + tbHour.Text + ":" + tbMinute.Text;
                        hfDate.Value = ddlMonth.SelectedValue + "|" + tbDay.Text + "|" + tbYear.Text + "|" + tbHour.Text + "|" + tbMinute.Text;

                        tbTitle_TextChanged(this, e);

                        // Set Categories
                        List<int> categories = bnn.GetAllCategoriesForPost(postID);
                        hfCategory.Value = string.Join("|", categories.ConvertAll<string>(x => x.ToString()).ToArray());
                        foreach (int category in categories)
                            cblCategories.Items.FindByValue(category.ToString()).Selected = true;

                        // Set Tags
                        List<int> tagsForPost = bnn.GetAllTagsForPost(postID);
                        if (tagsForPost.Count > 0)
                        {
                            List<TagInfo> allTags = bnn.GetAllTags(PortalId, ModuleId);
                            List<string> tags = new List<string>();
                            foreach (int tagForPost in tagsForPost)
                                foreach (TagInfo tag in allTags)
                                    if (tagForPost == tag.TagID)
                                    {
                                        tags.Add(tag.Tag);
                                        break;
                                    }
                            Session["tags"] = string.Join(",", tags.ToArray());
                        }
                        else
                            Session["tags"] = null;
                        BindTags();
                        
                    }
                    catch (Exception exc)
                    {
                        tbTitle.Text = exc.Message;
                    }
                }
            }
        }

        protected void tbTitle_TextChanged(object sender, EventArgs e)
        {
            tbTitle.Text = tbTitle.Text.Trim();

            if (!string.IsNullOrEmpty(tbTitle.Text))
            {
                BlogNetNukeController bnn = new BlogNetNukeController();
                string tabURL = string.Empty;
                if (!Convert.ToBoolean(bnn.GetSetting(-1, -1, "FriendlierUrls")))
                    tabURL = "TabID/" + TabId.ToString() + "/";

                string linkPath = "/" + tbYear.Text + "/" + ddlMonth.SelectedValue + "/" + tbDay.Text + "/";
                string pageName = Methods.GetSlug(tbTitle.Text);
                int pageCnt = 1;

                if ((!_isInEditMode) || (!bnn.ValidatePostTitle(PortalId, ModuleId, TabId, linkPath + pageName).Equals(new Guid(Request.QueryString["postID"]))))
                {
                    if (bnn.ValidatePostTitle(PortalId, ModuleId, TabId, linkPath + pageName) != Guid.Empty)
                    {
                        pageName = Methods.GetSlug(tbTitle.Text + " " + pageCnt.ToString());

                        while (bnn.ValidatePostTitle(PortalId, ModuleId, TabId, linkPath + pageName) != Guid.Empty)
                        {
                            pageCnt++;
                            pageName = Methods.GetSlug(tbTitle.Text + " " + pageCnt.ToString());
                        }
                    }
                }

                lblURL.Text = "http://" + Methods.GetTabPath(PortalId, TabId, ModuleId) + tabURL + linkPath.Substring(1) + Methods.GetPathExtension((XDocument)Session["BlogNetNuke"], pageName);
                permalinkLabel.Visible = true;
                hfSlug.Value = pageName;
                btnSave.Enabled = true;
            }
            else // Ensure textbox contains something
            {
                lblURL.Text = "&nbsp;";
                permalinkLabel.Visible = false;
                hfSlug.Value = string.Empty;
                btnSave.Enabled = false;
            }
        }

        protected void btnStatus_Click(object sender, EventArgs e)
        {
            lblStatus.Text = rblStatus.SelectedItem.Text;
            hfStatus.Value = rblStatus.SelectedValue;
            lbStatusToggle_Click(sender, e);
        }

        protected void lbStatusToggle_Click(object sender, EventArgs e)
        {
            pnlStatus.Visible = !pnlStatus.Visible;
            lbStatusToggle.Visible = !pnlStatus.Visible;
            rblStatus.SelectedValue = hfStatus.Value;
        }

        protected void btnDate_Click(object sender, EventArgs e)
        {
            lblDate.Text = ddlMonth.SelectedItem.Text + " " + tbDay.Text + ", " + tbYear.Text + " @ " + tbHour.Text + ":" + tbMinute.Text;
            hfDate.Value = ddlMonth.SelectedValue + "|" + tbDay.Text + "|" + tbYear.Text + "|" + tbHour.Text + "|" + tbMinute.Text;
            tbTitle_TextChanged(sender, e);
            lbDateToggle_Click(sender, e);
        }

        protected void lbDateToggle_Click(object sender, EventArgs e)
        {
            pnlDate.Visible = !pnlDate.Visible;
            lbDateToggle.Visible = !pnlDate.Visible;

            char[] splitter = { '|' };
            string[] dateInfo = hfDate.Value.Split(splitter);
            ddlMonth.SelectedValue = dateInfo[0];
            tbDay.Text = dateInfo[1];
            tbYear.Text = dateInfo[2];
            tbHour.Text = dateInfo[3];
            tbMinute.Text = dateInfo[4];
        }

        protected void lbCategoryToggle_Click(object sender, EventArgs e)
        {
            pnlCategory.Visible = !pnlCategory.Visible;
            lbCategoryAdd.Visible = !pnlCategory.Visible;
            tbCategory.Text = string.Empty;
            ddlCategory.SelectedIndex = -1;
        }

        private void BindCategories()
        {
            cblCategories.Items.Clear();
            cblCategories.Items.Add(new ListItem("Uncategorized", "-1"));
            
            BlogNetNukeController bnn = new BlogNetNukeController();
            cblCategories.DataSource = bnn.GetAllCategories(PortalId, ModuleId);
            cblCategories.DataTextField = "Category";
            cblCategories.DataValueField = "CategoryID";
            cblCategories.DataBind();

            char[] splitter = { '|' };
            string[] categoryInfo = hfCategory.Value.Split(splitter);
            foreach (string category in categoryInfo)
                cblCategories.Items.FindByValue(category).Selected = true;

        }

        protected void cblCategories_SelectedIndexChanged(object sender, EventArgs e)
        {
            List<string> selectedCategories = new List<string>();
            foreach (ListItem item in cblCategories.Items)
                if (item.Selected)
                    selectedCategories.Add(item.Value);

            hfCategory.Value = string.Join("|", selectedCategories.ToArray());
        }

        protected void btnCategoryAdd_Click(object sender, EventArgs e)
        {
            bool found = false;
            int categoryID = 0;

            BlogNetNukeController bnn = new BlogNetNukeController();
            List<CategoryInfo> categories = bnn.GetAllCategories(PortalId, ModuleId);

            // Make sure category doesn't exist before adding it again.
            foreach (CategoryInfo catInfo in categories)
                if (catInfo.Category.ToLower().Equals(tbCategory.Text.ToLower()))
                {
                    found = true;
                    categoryID = catInfo.CategoryID;  // if category already exists, store ID so it can be added to selected items
                    break;
                }

            if (!found)
            {
                CategoryInfo category = new CategoryInfo();
                category.Category = tbCategory.Text;
                category.Slug = Methods.GetSlug(tbCategory.Text);
                category.ParentID = Convert.ToInt32(ddlCategory.SelectedValue);
                category.ModuleID = ModuleId;
                category.PortalID = PortalId;

                categoryID = bnn.AddCategory(category);
            }

            // Get selected categories
            List<string> selectedCategories = new List<string>();
            foreach (ListItem item in cblCategories.Items)
                if (item.Selected)
                    selectedCategories.Add(item.Value);

            // If insert was done okay and category isn't already selected
            if (categoryID != 0 && !selectedCategories.Contains(categoryID.ToString()))
                selectedCategories.Add(categoryID.ToString());

            hfCategory.Value = string.Join("|", selectedCategories.ToArray());

            BindCategories();
            lbCategoryToggle_Click(sender, e);
        }

        protected void btnTagsAdd_Click(object sender, EventArgs e)
        {
            List<string> tagsList = new List<string>();
            char[] splitter = { ',' };
            string[] tags;

            if (Session["tags"] != null)
            {
                tags = Session["tags"].ToString().Split(splitter);
                foreach (string tag in tags)
                    tagsList.Add(tag);
            }

            if (!string.IsNullOrEmpty(tbTags.Text))
            {
                tags = tbTags.Text.Split(splitter);
                foreach (string tag in tags)
                    if (!tagsList.Contains(tag.Trim()))
                        tagsList.Add(tag.Trim());
            }

            Session["tags"] = string.Join(",", tagsList.ToArray());
            
            BindTags();
        }

        protected void ibTag_Command(object sender, CommandEventArgs e)
        {
            List<string> tagsList = new List<string>();
            char[] splitter = { ',' };
            string[] tags;

            // Remove from session
            tags = Session["tags"].ToString().Split(splitter);
            foreach (string tag in tags)
                if (!tag.Equals(e.CommandArgument))
                    tagsList.Add(tag);

            if (tagsList.Count > 0)
                Session["tags"] = string.Join(",", tagsList.ToArray());
            else
                Session.Remove("tags");

            BindTags();
        }

        private void BindTags()
        {
            pnlTags.Controls.Clear();
            tbTags.Text = string.Empty;
            
            List<string> tagsList = new List<string>();
            char[] splitter = { ',' };
            string[] tags;

            if (Session["tags"] != null)
            {
                tags = Session["tags"].ToString().Split(splitter);
                foreach (string tag in tags)
                    tagsList.Add(tag);
            }
            
            if (tagsList.Count > 0)
            {
                ImageButton ibTag;

                pnlTags.Controls.Add(new LiteralControl("<ul class=\"tagList\">"));
                for (int i = 0; i < tagsList.Count; i++)
                {
                    ibTag = new ImageButton();
                    ibTag.ID = "ibTag_" + i.ToString();
                    ibTag.ImageUrl = "/DesktopModules/BlogNetNuke/images/deleteTagOff.gif";
                    ibTag.Attributes.Add("onmouseover", "javascript:this.src='/DesktopModules/BlogNetNuke/images/deleteTagOn.gif';");
                    ibTag.Attributes.Add("onmouseout", "javascript:this.src='/DesktopModules/BlogNetNuke/images/deleteTagOff.gif';");
                    ibTag.CommandName = "delete";
                    ibTag.CommandArgument = tagsList[i];
                    ibTag.Command += new CommandEventHandler(ibTag_Command);
                    
                    pnlTags.Controls.Add(new LiteralControl("<li><span class=\"nowrap\">"));
                    pnlTags.Controls.Add(ibTag);
                    pnlTags.Controls.Add(new LiteralControl(tagsList[i]));
                    pnlTags.Controls.Add(new LiteralControl("</span></li>"));

                }
                pnlTags.Controls.Add(new LiteralControl("</ul>"));

                hfTags.Value = string.Join(",", tagsList.ToArray());
            }
        }

        protected void btnSave_Click(object sender, EventArgs e)
        {
            BlogNetNukeController bnn = new BlogNetNukeController();
            PostInfo post = new PostInfo();
            Guid postID = Guid.NewGuid();
            post.PostID = postID;
            post.PortalID = PortalId;
            post.ModuleID = ModuleId;
            post.PostTitle = tbTitle.Text;
            post.Slug = hfSlug.Value;
            post.Content = tbPost.RichText.Text;
            post.Excerpt = tbExcerpt.Text;
            post.AllowComments = cblDiscussion.Items[0].Selected;
            post.Status = (PostStatus)Convert.ToInt16(hfStatus.Value);

            char[] splitter = { '|' };
            string[] dateInfo = hfDate.Value.Split(splitter);
            post.PublishedDate = new DateTime(Convert.ToInt16(dateInfo[2]), Convert.ToInt16(dateInfo[0]), Convert.ToInt16(dateInfo[1]), Convert.ToInt16(dateInfo[3]), Convert.ToInt16(dateInfo[4]), 0); 
            
            post.PostPath = "/" + dateInfo[2] + "/" + dateInfo[0] + "/" + dateInfo[1] + "/" + hfSlug.Value;
            post.Keywords = tbKeywords.Text;
            post.Description = tbDescription.Text;
            post.AuthorID = UserId;

            if (_isInEditMode)
            {
                postID = new Guid(Request.QueryString["postID"]);
                post.PostID = postID;
                bnn.DeleteAllCategoriesForPost(postID);
                bnn.DeleteAllTagsForPost(postID);
                bnn.UpdatePost(post);
            }
            else
                bnn.InsertPost(post);
            
            // Only set TinyURL if TinyURL is currently empty and UseShortenedURL is set to true
            if (string.IsNullOrEmpty(lblTinyURL.Text.Trim()))
            {
                string useShortenedURL = bnn.GetSetting(PortalId, ModuleId, "UseShortenedURL");
                if ((!string.IsNullOrEmpty(useShortenedURL)) && Convert.ToBoolean(useShortenedURL))
                {
                    TinyURL url = new TinyURL(PortalId, ModuleId);
                    int urlID = -1;
                    string code = url.GenerateURL(out urlID);

                    bnn.AddTinyUrlRedirect(urlID, code, post.PostID);
                }
            }


            // Get all tags for module
            List<TagInfo> allTags = bnn.GetAllTags(PortalId, ModuleId);

            if (Session["tags"] != null)
            {
                char[] tagSplitter = { ',' };
                string[] tags;
                tags = Session["tags"].ToString().Split(tagSplitter);

                foreach (string tag in tags)
                {
                    TagInfo tInfo = new TagInfo();
                    tInfo.Tag = tag;
                    tInfo.Slug = Methods.GetSlug(tag);
                    tInfo.PortalID = PortalId;
                    tInfo.ModuleID = ModuleId;

                    int tagID = -1;
                    
                    // Check if tag already exists in database. If so, get tagID
                    foreach (TagInfo singleTag in allTags)
                        if (singleTag.Tag == tInfo.Tag)
                        {
                            tagID = singleTag.TagID;
                            break;
                        }
                    
                    // If not, add tag to database and get new tagID
                    if (tagID == -1)
                        tagID = bnn.AddTag(tInfo);
                    
                    // Add tag to post
                    bnn.AddTagToPost(tagID, postID);
                }
            }

            char[] catSplitter = { '|' };
            string[] categories = hfCategory.Value.Split(catSplitter);

            if (categories.Length > 0)
            {
                // For each selected category, add to post
                foreach (string category in categories)
                    bnn.AddCategoryToPost(Convert.ToInt32(category), postID);
            }
            else
                bnn.AddCategoryToPost(-1, postID); // Add to "Uncategorized" if no categories are selected
            
            Response.Redirect(lblURL.Text);
        }
    }
}